package com.oig.sys.log.aspect;


import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonConstants;
import com.oig.common.util.JsonUtil;
import com.oig.common.util.RequestHeaderUtil;
import com.oig.common.util.SpringContextUtil;
import com.oig.sys.log.dto.SysLogDto;
import com.oig.sys.log.event.SysLogEvent;
import com.oig.sys.log.util.LogTypeEnum;
import com.oig.sys.log.util.SysLogUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;


@Aspect
@Slf4j
public class SysLogAspect {


    @Around("@annotation(sysLog)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint point, com.oig.sys.log.annotation.SysLog sysLog) {
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();
        // 获取方法传入参数
        Object[] params = point.getArgs();
        log.debug("[类名]:{},[方法]:{}, [参数]:{}", strClassName, strMethodName, params);
        SysLogDto logDto = SysLogUtils.buildSysLog();
        logDto.setOptType(sysLog.value());
        //logDto.setContent(sysLog.apiUrl());
        if (StrUtil.isBlank(logDto.getApiUrl())){
            logDto.setApiUrl(sysLog.apiUrl());
        }
        if (StrUtil.isBlank(logDto.getOldval())){
            logDto.setOldval(JsonUtil.toJSONString(params));
        }
        logDto.setRemark("[类名]:"+strClassName+",[方法]:+"+strMethodName);
        final String traceId = MDC.get(CommonConstants.TRACE_ID);
        // 发送异步日志事件
        Long startTime = System.currentTimeMillis();
        Object obj ;
        try {
            obj = point.proceed();
            logDto.setResult(LogTypeEnum.NORMAL.getType());
            logDto.setNewval(obj==null?"":JsonUtil.toJSONString(obj));
        } catch (Exception e) {
            logDto.setResult(LogTypeEnum.ERROR.getType());
            logDto.setException(e.getMessage());
            log.error("log error ", e);
            throw e;
        } finally {
            if (StringUtils.isBlank(MDC.get(CommonConstants.TRACE_ID))) {
                MDC.put(CommonConstants.TRACE_ID, traceId);
            }
            logDto.setTraceId(traceId);
            Long endTime = System.currentTimeMillis();
            logDto.setExeTime(endTime - startTime);
            log.debug("publish event {}--token:{}", logDto.getExeTime(), RequestHeaderUtil.getToken());
            SpringContextUtil.publishEvent(new SysLogEvent(logDto, RequestHeaderUtil.getToken()));
        }
        return obj;
    }


//    private Object getObjectId(ProceedingJoinPoint point, Object[] params){
//        //获取方法，此处可将signature强转为MethodSignature
//        MethodSignature signature = (MethodSignature) point.getSignature();
//        Method method = signature.getMethod();
//        //参数注解，1维是参数，2维是注解
//        Annotation[][] annotations = method.getParameterAnnotations();
//
//        for (int i = 0; i < annotations.length; i++) {
//            Object param = params[i];
//            Annotation[] paramAnn = annotations[i];
//            //参数为空，直接下一个参数
//            if(param == null || paramAnn.length == 0){
//                continue;
//            }
//            Class<?> pClass = param.getClass();
//            for (Annotation annotation : paramAnn) {
//                //这里判断当前注解是否为SysLogObjectId.class
//                if(annotation.annotationType().equals(SysLogObjId.class)){
//                    if (ClassUtil.isBasicType(pClass)){ //如果是基础类型
//                        //不考虑联合主键的
//                        return param;
//                    } else if(ClassUtil.isNormalClass(pClass)) {   //是个标准类
//                        SysLogObjId sysLogObId = (SysLogObjId) annotation ;
//                        if (ReflectUtil.hasField(pClass, sysLogObId.idField())){    //包含了父类的属性字段
//                            return ReflectUtil.getFieldValue(param, sysLogObId.idField());
//                        }
//                    }
//                }
//            }
//        }
//        return null;
//    }
//
//
//    private Object getRtnObjectId(Object obj, String objIdFileName){
//        Class<?> rClass = obj.getClass();
//        if (ClassUtil.isBasicType(rClass)) { //如果是基础类型
//            return obj;
//        } else if(ClassUtil.isNormalClass(rClass)) {   //是个标准类
//            if (ReflectUtil.hasField(rClass, objIdFileName)){    //包含了父类的属性字段
//                return ReflectUtil.getFieldValue(obj, objIdFileName);
//            }
//        }
//        return null;
//    }

}
